package com.horse.cloud.framework.mybatis.datasource;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;


/**
 * @editor: intelliJ IDEA 16.1.3
 * @author: bing.Pan
 * @e-Mail: 15923508369@163.com
 * @gmDate: 2018/3/18/03/2018 16:17:下午4:17
 * @siDesc: mybatis 自动读写分离拦截器，在同一事物中强制路由到master库
 */



@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class }),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })
})

@Configuration
public class DataBasesRoutInterceptor implements Interceptor {

    protected static final Logger LOGGER = LoggerFactory.getLogger(DataBasesRoutInterceptor.class);
    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        Object[] objects = invocation.getArgs();
        MappedStatement ms = (MappedStatement) objects[0];

        //已指定强制使用
        if(DataSourceContextHolder.get().isForceUseMaster()){
            LOGGER.debug("【framework-mybatis】 开启事物，强制路由到master数据库");
            return invocation.proceed();
        }

        if(ms.getSqlCommandType().equals(SqlCommandType.SELECT)){
            LOGGER.debug("【framework-mybatis】 执行查询操作，使用slave数据库");
            DataSourceContextHolder.get().useDataBaseType(true,true);
            return invocation.proceed();

        }else{
            LOGGER.debug("【framework-mybatis】 执行CUD操作，使用master数据库");
            DataSourceContextHolder.get().useDataBaseType(false,true);
            return invocation.proceed();
        }


    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }


}
